﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ESP;
using TimbreRecognition.Recognition.ESP;

namespace TimbreRecognition.Recognition
{
    public class MFCCEnvironment : IEnvironment
    {

        private const double E = 0.01;

        private int inputCount;

        private int outputCount;

        private Dictionary<double[], double[]> trainingData ;

        private Dictionary<double[], double[]> validationData; 


        public MFCCEnvironment(TrainingSet trainingSet)
        {

            List<DataItem> data = new List<DataItem>();
            data.AddRange(trainingSet.TrainingData);
            data.AddRange(trainingSet.ValidationData);


            trainingData = data.ToDictionary(o => o.DataSeries, o => o.ExpectedOutput);

           // validationData = trainingSet.ValidationData.ToDictionary(o => o.DataSeries, o => o.ExpectedOutput);

           // trainingData.A

            inputCount = trainingSet.TrainingData[0].InputCount;

            outputCount = trainingSet.TrainingData[0].OutputCount;
        }

        public double evalNet(Network net)
        {
            //net.resetActivation();

            //double totalAverageError = 0;

            //foreach (DataItem dataItem in trainingSet.TrainingData)
            //{

            //    double[] input = dataItem.DataSeries;

            //    double[] actualResult = new double[getOutputSize()];

            //    net.activate(input, actualResult);

            //    double[] expectedOutput = dataItem.ExpectedOutput;

            //    if (actualResult.Length != expectedOutput.Length)
            //    {
            //        throw new ArgumentException("Expected and actual arrays should have equal length");
            //    }

            //    double totalError = 0;

            //    for (int i = 0; i < expectedOutput.Length; i++)
            //    {
            //        double error = expectedOutput[i] - actualResult[i];
            //        totalError += Math.Abs(error);
            //    }

            //    double averageError = totalError/expectedOutput.Length;
            //    totalAverageError += averageError;
            //}

            //return 1 - totalAverageError / trainingSet.TrainingData.Count;

            
            ResultTester tester = new ResultTester();
            double error = tester.GetErrorNumber(trainingData, new ESPNetworkWrapper(net));

            //Console.WriteLine("Accuracy on validation data = " + (1 - error));

            return 1 - error;
        }

        public void nextTask()
        {
            //To change body of implemented methods use File | Settings | File Templates.
        }

        public bool hasNextTask()
        {
            return false;
        }

        public void simplifyTask()
        {
            //To change body of implemented methods use File | Settings | File Templates.
        }

        public int getInputSize()
        {
            return inputCount;
        }

        public int getOutputSize()
        {
            return outputCount;
        }

        public double getMaxFitness()
        {
            return 1 - E; //To change body of implemented methods use File | Settings | File Templates.
        }

        public void setupInput(double[] input)
        {
            //To change body of implemented methods use File | Settings | File Templates.
        }

        public bool validate(Network network)
        {

            //ResultTester tester = new ResultTester();
            //double error = tester.GetErrorNumber(validationData, new ESPNetworkWrapper(network));

            //Console.WriteLine("Accuracy on validation data = " + (1 - error));

            //return error <= E;

             return false;
        }
    }

}
